/*
 * path.h
 *
 *  Created on: 08.03.2012
 *      Author: ignacio
 */

#ifndef PATH_H_
#define PATH_H_

#include "container.h"
#include "vector.h"

namespace neurignacio
{
/*
 * *********
 * Segment *
 * *********
 */
class Segment
{
// A segment is defined between a point A and a point B
public:
	Vector3 A;
	Vector3 B;
public:
	real getParameterClosestToPoint(const Vector3& point) const;

public:
	Segment(const Vector3& firstPoint, const Vector3& lastPoint) : A(firstPoint), B(lastPoint) {}
	friend ostream& operator<<(ostream& out, const Segment& segment);
	Vector3 getPointFromParameter(const real& parameter) const;
	Vector3 closestToPoint(const Vector3& point) const;
};

/*
 * ******
 * Path *
 * ******
 */
template<typename Type> class Path;

template<typename Type> ostream& operator<<(ostream& out, const Path<Type>& path);

template <typename Type>
class Path : public BaseContainer<Type>
{
public:
	Type closestToPoint(const Type& point) const;
	friend ostream& operator<< <>(ostream& out, const Path<Type>& path);
public:
	real getParameterClosestToPoint(const Type& point) const;
	Type getPointFromParameter(const real& parameter) const;
};

// Definitions for Type=Vector3
template<> Vector3 Path<Vector3>::closestToPoint(const Vector3& point) const;
template<> real Path<Vector3>::getParameterClosestToPoint(const Vector3& point) const;
template<> Vector3 Path<Vector3>::getPointFromParameter(const real& parameter) const;

typedef Path<Vector3> VectorPath;

} // end namespace neurignacio

namespace neurignacio{

template<typename Type>
ostream& operator<<(ostream& out, const Path<Type>& path)
{
	for (typename Path<Type>::const_iterator point=path.begin(); point!=path.end()-1; ++point)
	{
		out << *point << "->";
	}
	out << path.back();
	return out;
}

} // end namespace neurignacio

#endif /* PATH_H_ */
